Since 2015, JavaScript has improved immensely.
It’s much more pleasant to use it now than ever.
In this article, we’ll look at JavaScript promises.
Other Ways of Creating Promises
Other than using the Promise
constructor, we can create promises in other ways.
One way is the Promise.resolve
method.
It takes the resolved value of the promise as its argument.
And it returns a promise.
For instance, we can write:
Promise.resolve(1)
.then(x => console.log(x));
x
is the resolved value from Promise.resolve
.
If x
is a promise whose construction is the receiver, then the promise is unchanged.
For instance, if we have:
const p = new Promise(() => null);
console.log(Promise.resolve(p) === p);
then we get true
from the console log.
If the argument is a thenable and then the then
method in the argument is a function, then the resolved value with Promise.resolve
is the argument that we call the then
parameter with.
For example, if we have:
const thenableObj = {
then(reaction) {
reaction('foo');
}
};
const promise = Promise.resolve(thenableObj);
console.log(promise instanceof Promise);
promise.then(x => console.log(x));
We have a thenableObj
, which has the then
method.
It takes a reaction
function and we called it with 'foo'
.
Then we pass in an object to the Promise.resolve
method, which returns a promise.
If we check if promise
is an instance of a Promise
, then that returns true
.
We can also call then
on it with a callback to get the 'foo'
value, which is assigned to x
.
Promise.reject()
We can call Promise.reject()
to return a promise that’s rejected with a value.
For example, we can write:
const error = new Error('error');
Promise.reject(error)
.catch(err => console.log(err === error));
We pass in an error
object by passing that into the Promise.reject
method.
Then we call catch
by passing in a callback into it.
err
has the error object that we called Promise.reject
with, which should be the same as error
.
Chaining Promises
We can chain promises with then
as long as we return a promise.
Whatever we return in the then
callback will be the resolved value of the promise.
For instance, if we have:
Promise.resolve('bar')
.then(function(value1) {
return 'foo';
})
.then(function(value2) {
console.log(value2);
});
Then value2
would be 'foo'
.
This lets us flatten promises chains.
Instead of writing:
Promise.resolve('bar')
.then(function(value1) {
Promise.resolve('foo')
.then(function(value2) {
//...
});
})
We write:
Promise.resolve('bar')
.then(function(value1) {
return 'foo';
})
.then(function(value2) {
//...
});
Catching Errors
We can catch errors with the catch
method.
For example, we can write:
Promise.reject(new Error('error'))
.catch(function() {
return 'error occurred';
})
.then(function(value) {
//...
});
We called catch
to catch the error from the rejected promise and run our own code.
This lets us set some value for the next promise to use.
Throw an Exception
We can throw an exception in the then
callback, then the promise returned will be rejected.
For instance, we can write:
Promise.resolve()
.then(function(value) {
throw new Error();
})
.catch(function(reason) {
// ...
});
We threw an error in the then
callback, so the catch
callback will run.
Conclusion
We can resolve a promise with a value so the next one can be invoked.
Also, we can reject promises and catch the error with catch
.